package net.mgsx.product.t2m.modisco.impact;
import net.mgsx.product.t2m.modisco.tools.ModiscoUtils;

import org.eclipse.gmt.modisco.java.ASTNode;
import org.eclipse.gmt.modisco.java.AbstractMethodDeclaration;
import org.eclipse.gmt.modisco.java.AbstractTypeDeclaration;
import org.eclipse.gmt.modisco.java.Block;
import org.eclipse.gmt.modisco.java.BodyDeclaration;
import org.eclipse.gmt.modisco.java.CompilationUnit;
import org.eclipse.gmt.modisco.java.EnumConstantDeclaration;
import org.eclipse.gmt.modisco.java.Expression;
import org.eclipse.gmt.modisco.java.FieldDeclaration;
import org.eclipse.gmt.modisco.java.Initializer;
import org.eclipse.gmt.modisco.java.Statement;
import org.eclipse.gmt.modisco.infra.query.core.exception.ModelQueryExecutionException;
import org.eclipse.gmt.modisco.infra.query.core.java.IJavaModelQuery;
import org.eclipse.gmt.modisco.infra.query.core.java.ParameterValueList;

public class GetWeight implements IJavaModelQuery<ASTNode, Integer> {
	public Integer evaluate(final ASTNode context, final ParameterValueList parameterValues)
			throws ModelQueryExecutionException {
		Integer weight = 0;
		if(context == null)
		{
			ModiscoUtils.getLogger().logWarning("unknown weight for null node");
		}
		else if(context instanceof CompilationUnit)
		{
			for(AbstractTypeDeclaration declaration : ((CompilationUnit) context).getTypes())
			{
				weight += evaluate(declaration, parameterValues);
			}
		}
		else if(context instanceof AbstractTypeDeclaration)
		{
			for(BodyDeclaration declaration : ((AbstractTypeDeclaration) context).getBodyDeclarations())
			{
				weight += evaluate(declaration, parameterValues);
			}
			weight += 1;
		}
		else if(context instanceof AbstractMethodDeclaration)
		{
			weight += evaluate(((AbstractMethodDeclaration) context).getBody(), parameterValues);
			weight += 1;
		}
		else if(context instanceof EnumConstantDeclaration)
		{
			for(Expression expression : ((EnumConstantDeclaration) context).getArguments())
			{
				weight += evaluate(expression, parameterValues);
			}
			weight += 1;
		}
		else if(context instanceof FieldDeclaration)
		{
			weight += 1;
		}
		else if(context instanceof Initializer)
		{
			weight += evaluate(((Initializer) context).getBody(), parameterValues);
		}
		else if(context instanceof AbstractMethodDeclaration)
		{
			weight += ModiscoUtils.getElements(context, Statement.class).size();
		}
		else if(context instanceof Block)
		{
			for(Statement expression : ((Block) context).getStatements())
			{
				weight += evaluate(expression, parameterValues);
			}
		}
		else if(context instanceof Statement)
		{
			weight += 1;
		}
		else
		{
			ModiscoUtils.getLogger().logWarning("unknown weight for " + context.eClass().getName());
		}
		
		return weight;
	}
}
